home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 1 (Walnut Creek)
/
Aminet - June 1993 [Walnut Creek].iso
/
usenet
/
sources
/
volume2
/
fun
/
nethack.a1
< prev
next >
Wrap
Text File
|
1988-12-02
|
56KB
|
2,242 lines
Path: xanth!nic.MR.NET!hal!cwjcc!gatech!rutgers!mit-eddie!ll-xn!adelie!infinet!ulowell!page
From: page@swan.ulowell.edu (Bob Page)
Newsgroups: comp.sources.amiga
Subject: v02i068: nethack - D&D-like game (amiga additions), Part01/02
Message-ID: <10399@swan.ulowell.edu>
Date: 1 Dec 88 23:37:47 GMT
Organization: University of Lowell, Computer Science Dept.
Lines: 2231
Approved: page@swan.ulowell.edu
Submitted-by: u211344@hnykun11.bitnet (Olaf 'Rhialto' Seibert)
Posting-number: Volume 2, Issue 68
Archive-name: fun/nethack.a1
[The Amiga additional files plus the diffs, when applied to the
original nethack source, should produce an Amiga executable version of
nethack. ..Bob]
# This is a shell archive.
# Remove everything above and including the cut line.
# Then run the rest of the file through sh.
#----cut here-----cut here-----cut here-----cut here----#
#!/bin/sh
# shar: Shell Archiver
# Run the following text with /bin/sh to create:
# amigaDos.c
# amigaMenu.c
# amigaTTY.c
# amigaTermcap.c
# amigaUnix.c
# amigaWindow.c
# This archive created: Thu Dec 1 17:50:06 1988
cat << \SHAR_EOF > amigaDos.c
/* SCCS Id: @(#)amigaDos.c msdos.c - Amiga version 2.3 88/07/24
/* An assortment of MSDOS functions.
*/
#include <stdio.h>
#include "hack.h"
#undef TRUE
#undef FALSE
#undef COUNT
#include <libraries/dos.h>
extern char Initialized;
struct FileLock *Lock(), *CurrentDir(); /* Cheating - BCPL pointers */
struct FileHandle *Open(); /* Cheating - BCPL pointer */
long Read(), Write(), IoErr(), AvailMem();
void *malloc();
char *rindex(), *index();
int Enable_Abort = 0; /* for stdio package */
/* Initial path, so we can find NetHack.cnf */
char PATH[PATHLEN] = "Ram:;df0:;NetHack:";
void
flushout()
{
(void) fflush(stdout);
}
getuid() {
return 1;
}
/*
* Actually make up a process id.
* Makes sure one can mess less with saved levels...
*/
int getpid()
{
static short pid;
while (pid == 0) {
struct DateStamp dateStamp;
pid = rnd(30000);
pid += DateStamp(&dateStamp); /* More or less random */
pid ^= (short) (dateStamp.ds_Days >> 16) ^
(short) (dateStamp.ds_Days) ^
(short) (dateStamp.ds_Minute) +
(short) (dateStamp.ds_Tick);
pid %= 30000;
}
return pid;
}
char *
getlogin() {
return ((char *) NULL);
}
int
abs(x)
int x;
{
return x < 0? -x: x;
}
#ifdef REDO
tgetch() {
char ch, popch();
if (!(ch = popch())) {
ch = WindowGetchar();
}
return ((ch == '\r') ? '\n' : ch);
}
#else /* REDO /**/
tgetch() {
char ch;
ch = WindowGetchar();
return ((ch == '\r') ? '\n' : ch);
}
#endif /* REDO /**/
#ifdef DGK
# include <ctype.h>
# include <fcntl.h>
# define Sprintf (void) sprintf
# ifdef SHELL
dosh()
{
pline("No mysterious force prevented you from using multitasking.");
return 0;
}
# endif /* SHELL */
/* construct the string file.level */
void
name_file(file, level)
char *file;
int level;
{
char *tf;
if (tf = rindex(file, '.'))
Sprintf(tf+1, "%d", level);
}
#define ID_DOS1_DISK 'DOS\1'
/*
* This routine uses an approximation of the free bytes on a disk.
* How large a file you can actually write depends on the number of
* extension blocks you need for it.
* An iterative approach is used that (hopefully) mimics the AmigaDOG
* (yuck, tripos) block allocation sequence used when a file grows.
*/
long
freediskspace(path)
char *path;
{
register long freeBytes = 0;
register struct InfoData *infoData; /* Remember... longword aligned */
char fileName[32];
/*
* Find a valid path on the device of which we want the free space.
* If there is a colon in the name, it is an absolute path
* and all up to the colon is everything we need.
* Remember slashes in a volume name are allowed!
* If there is no colon, it is relative to the current directory,
* so must be on the current device, so "" is enough...
*/
{
register char *colon;
strncpy(fileName, path, sizeof(fileName)-1);
fileName[31] = 0;
if (colon = index(fileName, ':'))
colon[1] = '\0';
else
fileName[0] = '\0';
}
if (infoData = malloc(sizeof(*infoData))) {
struct FileLock *fileLock; /* Cheating */
if (fileLock = Lock(fileName, SHARED_LOCK)) {
if (Info(fileLock, infoData)) {
/* We got a kind of DOS volume, since we can Lock it. */
/* Calculate number of blocks available for new file */
/* Kludge for the ever-full VOID: (oops RAM:) device */
if (infoData->id_UnitNumber == -1 &&
infoData->id_NumBlocks == infoData->id_NumBlocksUsed) {
freeBytes = AvailMem(0L) - 48*1024;
/* Just a stupid guess at the */
/* Ram-Handler overhead per block: */
freeBytes -= freeBytes/16;
} else {
/* Normal kind of DOS file system device/volume */
register long fileBlocks;
register long extensionPointers;
freeBytes = infoData->id_NumBlocks -
infoData->id_NumBlocksUsed -
1; /* for file header */
if (infoData->id_DiskType == ID_DOS_DISK)
/* BytesPerBlock is 488 on floppies */
extensionPointers = (infoData->id_BytesPerBlock-200)/4;
else
/* Presumably it is 512 on ID_DOS1_DISK. */
extensionPointers = (infoData->id_BytesPerBlock-224)/4;
/* Number of blocks left to simulate */
fileBlocks = freeBytes;
/* Need another extension block? */
while (fileBlocks > extensionPointers) {
/* Get an extension block. One block less free. */
freeBytes--;
fileBlocks--;
/* to accomodate 72 extra data blocks */
fileBlocks -= extensionPointers;
}
freeBytes *= infoData->id_BytesPerBlock;
}
if (freeBytes < 0)
freeBytes = 0;
}
UnLock(fileLock);
}
free(infoData);
}
return freeBytes;
}
long
filesize(file)
char *file;
{
register struct FileLock *fileLock;
register struct FileInfoBlock *fileInfoBlock;
register long size = 0;
if (fileInfoBlock = malloc(sizeof(*fileInfoBlock))) {
if (fileLock = Lock(file, SHARED_LOCK)) {
if (Examine(fileLock, fileInfoBlock)) {
size = fileInfoBlock->fib_Size;
}
UnLock(fileLock);
}
free(fileInfoBlock);
}
return size;
}
/*
* On the Amiga, looking if a specific file exists is much faster
* than sequentially reading a directory.
*/
void
eraseall(path, files)
char *path, *files;
{
char buf[FILENAME];
short i;
struct FileLock *fileLock, *dirLock;
if (dirLock = Lock(path)) {
dirLock = CurrentDir(dirLock);
strcpy(buf, files);
for (i = 0; i < MAXLEVEL; i++) {
name_file(buf, i);
if (fileLock = Lock(buf, SHARED_LOCK)) {
UnLock(fileLock);
DeleteFile(buf);
}
}
UnLock(CurrentDir(dirLock));
}
}
/* This size makes that most files can be copied with two Read()/Write()s */
#define COPYSIZE 4096
char *CopyFile(from, to)
char *from, *to;
{
register struct FileHandle *fromFile, *toFile;
register char *buffer;
register long size;
char *error = NULL;
if (buffer = malloc(COPYSIZE)) {
if (fromFile = Open(from, MODE_OLDFILE)) {
if (toFile = Open(to, MODE_NEWFILE)) {
while (size = Read(fromFile, buffer, (long)COPYSIZE)) {
if (size != Write(toFile, buffer, size)) {
error = "Write error";
break;
}
}
Close(toFile);
} else /* Can't open destination file */
error = "Cannot open destination";
Close(fromFile);
} else /* Cannot open source file. Should not happen. */
error = "Huh?? Cannot open source??";
free(buffer);
return error;
} else /* Cannot obtain buffer for copying */
return "No Memory !";
}
void
copybones(mode)
int mode;
{
struct FileLock *fileLock;
char from[FILENAME], to[FILENAME];
char *frompath, *topath, *status;
short i;
extern int saveprompt;
if (!ramdisk)
return;
frompath = (mode != TOPERM) ? permbones : levels;
topath = (mode == TOPERM) ? permbones : levels;
/* Remove any bones files in `to' directory. */
eraseall(topath, allbones);
/* Copy `from' to `to' */
strcpy(from, frompath);
strcat(from, allbones);
strcpy(to, topath);
strcat(to, allbones);
for (i = 1; i < MAXLEVEL; i++) {
name_file(from, i);
name_file(to, i);
if (fileLock = Lock(from, SHARED_LOCK)) {
UnLock(fileLock);
if (status = CopyFile(from, to))
goto failed;
}
}
/*
* The last file got there. Remove the ramdisk bones files.
*/
if (mode == TOPERM)
eraseall(frompath, allbones);
return;
/* Last file didn't get there. */
failed:
msmsg("Cannot copy `%s' to `%s'\n(%s)\n", from, to, status);
if (mode == TOPERM) {
msmsg("Bones will be left in `%s'\n",
*frompath ? frompath : hackdir);
return;
} else {
/* Remove all bones files on the RAMdisk */
eraseall(levels, allbones);
playwoRAMdisk();
}
}
playwoRAMdisk()
{
msmsg("Do you wish to play without a RAMdisk (y/n) ? ");
/* Set ramdisk false *before* exit'ing (because msexit calls
* copybones)
*/
ramdisk = FALSE;
if (getchar() != 'y') {
settty("Be seeing you ...\n");
exit(0);
}
set_lock_and_bones();
return;
}
saveDiskPrompt(start)
{
extern int saveprompt;
char buf[BUFSIZ], *bp;
struct FileLock *fileLock;
if (saveprompt) {
/* Don't prompt if you can find the save file */
if (fileLock = Lock(SAVEF, SHARED_LOCK)) {
UnLock(fileLock);
return 1;
}
remember_topl();
home();
cl_end();
msmsg("If save file is on a SAVE disk, put that disk in now.\n");
cl_end();
msmsg("File name (default `%s'%s) ? ", SAVEF,
start ? "" : ", <Esc> cancels save");
getlin(buf);
home();
cl_end();
curs(1, 2);
cl_end();
if (!start && *buf == '\033')
return 0;
/* Strip any whitespace. Also, if nothing was entered except
* whitespace, do not change the value of SAVEF.
*/
for (bp = buf; *bp; bp++)
if (!isspace(*bp)) {
strncpy(SAVEF, bp, PATHLEN);
break;
}
}
return 1;
}
/* Return 1 if the record file was found */
static boolean
record_exists()
{
FILE *file;
if (file = fopenp(RECORD, "r")) {
fclose(file);
return TRUE;
}
return FALSE;
}
/* Prompt for game disk, then check for record file.
*/
void
gameDiskPrompt()
{
extern int saveprompt;
if (record_exists())
return;
if (saveprompt) {
(void) putchar('\n');
getreturn("when the GAME disk has been put in");
}
if (!record_exists()) {
msmsg("\n\nWARNING: can't find record file `%s'!\n", RECORD);
msmsg("If the GAME disk is not in, put it in now.\n");
getreturn("to continue");
}
}
/* Read configuration */
void
read_config_file()
{
char tmp_ramdisk[PATHLEN], tmp_levels[PATHLEN];
char buf[BUFSZ], *bufp;
FILE *fp, *fopenp();
extern char plname[];
extern int saveprompt;
tmp_ramdisk[0] = 0;
tmp_levels[0] = 0;
if ((fp = fopenp(configfile, "r")) == NULL) {
msmsg("Warning: no configuration file!\n");
getreturn("to continue");
return;
}
while (fgets(buf, BUFSZ, fp)) {
if (*buf == '#')
continue;
/* remove trailing whitespace */
bufp = index(buf, '\n');
while (bufp > buf && isspace(*bufp))
bufp--;
if (bufp == buf)
continue; /* skip all-blank lines */
else
*(bufp + 1) = 0; /* 0 terminate line */
/* find the '=' */
if (!(bufp = index(buf, '='))) {
msmsg("Bad option line: '%s'\n", buf);
getreturn("to continue");
continue;
}
/* skip whitespace between '=' and value */
while (isspace(*++bufp))
;
/* Go through possible variables */
if (!strncmp(buf, "HACKDIR", 4)) {
strncpy(hackdir, bufp, PATHLEN);
} else if (!strncmp(buf, "RAMDISK", 3)) {
strncpy(tmp_ramdisk, bufp, PATHLEN);
} else if (!strncmp(buf, "LEVELS", 4)) {
strncpy(tmp_levels, bufp, PATHLEN);
} else if (!strncmp(buf, "OPTIONS", 4)) {
parseoptions(bufp, TRUE);
if (plname[0]) /* If a name was given */
plnamesuffix(); /* set the character class */
} else if (!strncmp(buf, "SAVE", 4)) {
char *ptr;
if (ptr = index(bufp, ';')) {
*ptr = '\0';
if (*(ptr+1) == 'n' || *(ptr+1) == 'N')
saveprompt = FALSE;
}
(void) strncpy(SAVEF, bufp, PATHLEN);
append_slash(SAVEF);
#ifdef GRAPHICS
} else if (!strncmp(buf, "GRAPHICS", 4)) {
unsigned int translate[MAXPCHARS];
int i;
if ((i = sscanf(bufp, "%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d",
&translate[ 0], &translate[ 1], &translate[ 2],
&translate[ 3], &translate[ 4], &translate[ 5],
&translate[ 6], &translate[ 7], &translate[ 8],
&translate[ 9], &translate[10], &translate[11],
&translate[12], &translate[13], &translate[14],
&translate[15], &translate[16], &translate[17])) < 0) {
msmsg ("Syntax error in GRAPHICS\n");
getreturn("to continue");
} /* Yuck! Worked only with low-byte first!!! */
/*
* You could have problems here if you configure FOUNTAINS, SPIDERS or NEWCLASS
* in or out and forget to change the tail entries in your graphics string.
*/
#define SETPCHAR(f, n) showsyms.f = (i > n) ? translate[n] : defsyms.f
SETPCHAR(stone, 0);
SETPCHAR(vwall, 1);
SETPCHAR(hwall, 2);
SETPCHAR(tlcorn, 3);
SETPCHAR(trcorn, 4);
SETPCHAR(blcorn, 5);
SETPCHAR(brcorn, 6);
SETPCHAR(door, 7);
SETPCHAR(room, 8);
SETPCHAR(corr, 9);
SETPCHAR(upstair, 10);
SETPCHAR(dnstair, 11);
SETPCHAR(trap, 12);
#ifdef FOUNTAINS
SETPCHAR(pool, 13);
SETPCHAR(fountain, 14);
#endif
#ifdef NEWCLASS
SETPCHAR(throne, 15);
#endif
#ifdef SPIDERS
SETPCHAR(web, 16);
#endif
#ifdef SINKS
SETPCHAR(sink, 17);
#endif
#undef SETPCHAR
#endif /* GRAPHICS */
} else if (!strncmp(buf, "PATH", 4)) {
strncpy(PATH, bufp, PATHLEN);
} else {
msmsg("Bad option line: '%s'\n", buf);
getreturn("to continue");
}
}
fclose(fp);
strcpy(permbones, tmp_levels);
if (tmp_ramdisk[0]) {
strcpy(levels, tmp_ramdisk);
if (strcmpi(permbones, levels)) /* if not identical */
ramdisk = TRUE;
} else
strcpy(levels, tmp_levels);
strcpy(bones, levels);
}
/* Set names for bones[] and lock[] */
void
set_lock_and_bones()
{
if (!ramdisk) {
strcpy(levels, permbones);
strcpy(bones, permbones);
}
append_slash(permbones);
append_slash(levels);
append_slash(bones);
strcat(bones, allbones);
strcpy(lock, levels);
strcat(lock, alllevels);
}
/*
* Add a slash to any name not ending in / or :. There must
* be room for the /.
*/
void
append_slash(name)
char *name;
{
char *ptr;
if (!*name)
return;
ptr = name + (strlen(name) - 1);
if (*ptr != '/' && *ptr != ':') {
*++ptr = '/';
*++ptr = '\0';
}
}
void
getreturn(str)
char *str;
{
int ch;
msmsg("Hit <RETURN> %s.", str);
while ((ch = getchar()) != '\n')
;
}
void
msmsg(fmt, a1, a2, a3)
char *fmt;
long a1, a2, a3;
{
printf(fmt, a1, a2, a3);
(void) fflush(stdout);
}
/* Follow the PATH, trying to fopen the file.
*/
#define PATHSEP ';'
#undef fopen
FILE *
fopenp(name, mode)
register char *name, *mode;
{
char buf[BUFSIZ], *bp, *pp, lastch;
FILE *fp;
register struct FileLock *theLock;
/* Try the default directory first. Then look along PATH.
*/
strcpy(buf, name);
if (theLock = Lock(buf, SHARED_LOCK)) {
UnLock(theLock);
if (fp = fopen(buf, mode))
return fp;
}
pp = PATH;
while (pp && *pp) {
bp = buf;
while (*pp && *pp != PATHSEP)
lastch = *bp++ = *pp++;
if (lastch != ':' && lastch != '/' && bp != buf)
*bp++ = '/';
strcpy(bp, name);
if (theLock = Lock(buf, SHARED_LOCK)) {
UnLock(theLock);
if (fp = fopen(buf, mode))
return fp;
}
if (*pp)
pp++;
}
return NULL;
}
#endif /* DGK */
#ifdef CHDIR
/*
* A not general-purpose directory changing routine.
* Assumes you want to return to the original directory eventually,
* by chdir()ing to orgdir.
* Assumes -1 is not a valid lock, since 0 is valid.
*/
#define NO_LOCK ((struct FileLock *) -1)
char orgdir[1];
static struct FileLock *OrgDirLock = NO_LOCK;
chdir(dir)
char *dir;
{
if (dir == orgdir) {
/* We want to go back to where we came from. */
if (OrgDirLock != NO_LOCK) {
UnLock(CurrentDir(OrgDirLock));
OrgDirLock = NO_LOCK;
}
} else {
/*
* Go to some new place. If still at the original
* directory, save the FileLock.
*/
struct FileLock *newDir;
if (newDir = Lock(dir, SHARED_LOCK)) {
if (OrgDirLock == NO_LOCK) {
OrgDirLock = CurrentDir(newDir);
} else {
UnLock(CurrentDir(newDir));
}
} else {
return -1; /* Failed */
}
}
/* CurrentDir always succeeds if you have a lock */
return 0;
}
#endif
/* Chdir back to original directory
*/
#undef exit
void
msexit(code)
{
#ifdef CHDIR
extern char orgdir[];
#endif
#ifdef DGK
(void) fflush(stdout);
if (ramdisk)
copybones(TOPERM);
#endif
#ifdef CHDIR
chdir(orgdir); /* chdir, not chdirx */
#endif
/* Never know when exit is called... */
if (Initialized && (curx != 1 || cury != 1))
getret();
CleanUp();
exit(code);
}
/*
* Strcmp while ignoring case. Not general-purpose, so static.
*/
static int strcmpi(a, b)
register char *a, *b;
{
while (tolower(*a) == tolower(*b)) {
if (!*a) /* *a == *b, so at end of both strings */
return 0; /* equal. */
a++;
b++;
}
return 1;
}
/*
* cmpmem - used to compare two struct symbols, in lev.c
*/
cmpmem(a, b, size)
register unsigned char *a, *b;
register int size;
{
while (size--) {
if (*a++ != *b++)
return 1; /* not equal */
}
return 0; /* equal */
}
SHAR_EOF
cat << \SHAR_EOF > amigaMenu.c
/*
* amigaMenu.c (C) Copyright 1988 by Olaf Seibert (KosmoSoft)
*
* Originally by John Toebes.
*/
#define TEXT(nam,str) \
static struct IntuiText nam = {0,1,JAM2,0,0,NULL,(UBYTE *)str,NULL}
/* Commands */
TEXT(T_HELP, "? display help");
TEXT(T_o, "O set options");
TEXT(T_SHELL, "! AMIGADOS commands");
TEXT(T_v, "v version number");
TEXT(T_CR, "^R redraw screen");
TEXT(T_CP, "^P repeat last message");
TEXT(T_Q, "Q quit game");
TEXT(T_S, "S save the game");
/* Inventory */
TEXT(T_i, "i inventory");
TEXT(T_p, "p pay your bill");
TEXT(T_d, "d drop an object");
TEXT(T_D, "D Drop several things");
TEXT(T_COMMA, ", Pickup an object");
TEXT(T_SLASH, "/ identify something");
TEXT(T_c, "c call class of objects");
TEXT(T_C, "C Christen a monster");
/* Actions */
TEXT(T_a, "a apply/use something");
TEXT(T_e, "e eat something");
TEXT(T_q, "q quaff a potion");
TEXT(T_r, "r read a scroll");
TEXT(T_t, "t throw/shoot weapon");
TEXT(T_z, "z zap a wand");
/* Preparations */
TEXT(T_w, "w wield a weapon");
TEXT(T_P, "P Put on ring");
TEXT(T_R, "R Remove ring");
TEXT(T_T, "T Take off armor");
TEXT(T_W, "W Wear armor");
TEXT(T_WPN, ") current weapon");
TEXT(T_ARMOR, "[ current armor");
TEXT(T_RING, "= current rings");
/* Movement */
TEXT(T_E, "E Engrave msg on floor");
TEXT(T_s, "s search");
TEXT(T_UP, "< Go up stairs");
TEXT(T_DOWN, "> Go down stairs");
TEXT(T_WAIT, ". wait a moment");
TEXT(T_CT, "^T Teleport");
#define IFLAGS ITEMENABLED|ITEMTEXT|HIGHCOMP
#define IDATA(cmd,str,off) 0,off,WDT,9,IFLAGS,0,(APTR)&str,NULL,cmd,NULL,NULL
/* Commands */
#undef WDT
#define WDT 184
static struct MenuItem cmdsub[] = {
{ &cmdsub[1], IDATA('?', T_HELP, 0) }, /* display help */
{ &cmdsub[2], IDATA('O', T_o, 10) }, /* set options */
{ &cmdsub[3], IDATA('!', T_SHELL, 20) }, /* AMIGADOS commands */
{ &cmdsub[4], IDATA('v', T_v, 30) }, /* version number */
{ &cmdsub[5], IDATA(022, T_CR, 40) }, /*R redraw screen */
{ &cmdsub[6], IDATA(024 ,T_CP, 50) }, /*P repeat last message */
{ &cmdsub[7], IDATA('Q', T_Q, 60) }, /* quit game */
{ NULL, IDATA('S', T_S, 70) } /* save the game */
};
/* Inventory */
#undef WDT
#define WDT 200
static struct MenuItem invsub[] = {
{ &invsub[1], IDATA('i', T_i, 0) }, /* inventory */
{ &invsub[2], IDATA('p', T_p, 10) }, /* pay your bill */
{ &invsub[3], IDATA('d', T_d, 20) }, /* drop an object */
{ &invsub[4], IDATA('D', T_D, 30) }, /* Drop several things */
{ &invsub[5], IDATA(',', T_COMMA, 40) }, /* Pickup an object */
{ &invsub[6], IDATA('/', T_SLASH, 50) }, /* identify something */
{ &invsub[7], IDATA('c', T_c, 60) }, /* call a class of objects */
{ NULL, IDATA('C', T_C, 70) } /* Christen a monster */
};
/* Actions */
#undef WDT
#define WDT 184
static struct MenuItem actsub[] = {
{ &actsub[1], IDATA('a', T_a, 0) }, /* apply/use something */
{ &actsub[2], IDATA('e', T_e, 10) }, /* eat something */
{ &actsub[3], IDATA('q', T_q, 20) }, /* quaff a potion */
{ &actsub[4], IDATA('r', T_r, 30) }, /* read a scroll */
{ &actsub[5], IDATA('t', T_t, 40) }, /* throw/shoot weapon */
{ NULL, IDATA('z', T_z, 50) } /* zap a wand */
};
/* Preparations */
#undef WDT
#define WDT 144
static struct MenuItem armsub[] = {
{ &armsub[1], IDATA('w', T_w, 0) }, /* wield a weapon */
{ &armsub[2], IDATA('P', T_P, 10) }, /* Put on ring */
{ &armsub[3], IDATA('R', T_R, 20) }, /* Remove ring */
{ &armsub[4], IDATA('T', T_T, 30) }, /* Take off armor */
{ &armsub[5], IDATA('W', T_W, 40) }, /* Wear armor */
{ &armsub[6], IDATA(')', T_WPN, 50) }, /* current weapon */
{ &armsub[7], IDATA('[', T_ARMOR, 60) }, /* current armor */
{ NULL, IDATA('=', T_RING, 70) } /* current rings */
};
/* Movement */
#undef WDT
#define WDT 192
static struct MenuItem movsub[] = {
{ &movsub[1], IDATA('E', T_E, 0) }, /* Engrave msg on floor */
{ &movsub[2], IDATA('s', T_s, 10) }, /* search */
{ &movsub[3], IDATA('<', T_UP, 20) }, /* Go up stairs */
{ &movsub[4], IDATA('>', T_DOWN, 30) }, /* Go down stairs */
{ &movsub[5], IDATA('.', T_WAIT, 40) }, /* wait a moment */
{ NULL, IDATA(024, T_CT, 50) } /*T Teleport */
};
/* Menustrip */
/* Width = #letters * 8 + 8 */
struct Menu HackMenu[] = {
{ &HackMenu[1], 10,0, 72,0,MENUENABLED,"Commands", &cmdsub[0] }, /*8*/
{ &HackMenu[2], 82,0, 80,0,MENUENABLED,"Inventory", &invsub[0] }, /*9*/
{ &HackMenu[3],162,0, 64,0,MENUENABLED,"Actions", &actsub[0] }, /*7*/
{ &HackMenu[4],226,0,104,0,MENUENABLED,"Preparations", &armsub[0] }, /*12*/
{ NULL, 330,0, 72,0,MENUENABLED,"Movement", &movsub[0] } /*8*/
};
SHAR_EOF
cat << \SHAR_EOF > amigaTTY.c
/* SCCS Id: @(#)amigaTTY.c 2.3 88/07/25
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* tty.c - (Amiga) version */
#include <stdio.h>
#include "hack.h"
#include "func_tab.h"
extern int Enable_Abort;
static char erase_char, kill_char;
/*
* Get initial state of terminal, set ospeed (for termcap routines)
* and switch off tab expansion if necessary.
* Called by startup() in termcap.c and after returning from ! or ^Z
*/
gettty()
{
erase_char = 127; /* DEL */
kill_char = 21; /* cntl-U */
flags.cbreak = TRUE;
Enable_Abort = 0;
curx = 1;
cury = 1;
}
/* reset terminal to original state */
settty(s)
char *s;
{
end_screen();
if (s) {
printf(s);
curx = FAR; /* For msexit(): don't exit immediately */
}
(void) fflush(stdout);
/* Do not close the screen, that is done in msexit() */
}
/* fatal error */
/*VARARGS1*/
error(s,x,y)
char *s;
{
end_screen();
putchar('\n');
printf(s,x,y);
putchar('\n');
abort(1);
}
/*
* Read a line closed with '\n' into the array char bufp[BUFSZ].
* (The '\n' is not stored. The string is closed with a '\0'.)
* Reading can be interrupted by an escape ('\033') - now the
* resulting string is "\033".
*/
getlin(bufp)
register char *bufp;
{
register char *obufp = bufp;
register int c;
flags.toplin = 2; /* nonempty, no --More-- required */
for(;;) {
(void) fflush(stdout);
if((c = getchar()) == EOF) {
*bufp = 0;
return;
}
if(c == '\033') {
*obufp = c;
obufp[1] = 0;
return;
}
if(c == erase_char || c == '\b') {
if(bufp != obufp) {
bufp--;
putstr("\b \b"); /* putsym converts \b */
} else bell();
} else if(c == '\n') {
*bufp = 0;
return;
} else if(' ' <= c && c < '\177') {
/* avoid isprint() - some people don't have it
' ' is not always a printing char */
*bufp = c;
bufp[1] = 0;
putstr(bufp);
if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
bufp++;
} else if(c == kill_char || c == '\177') { /* Robert Viduya */
/* this test last - @ might be the kill_char */
while(bufp != obufp) {
bufp--;
putstr("\b \b");
}
} else
bell();
}
}
getret()
{
cgetret("");
}
cgetret(s)
register char *s;
{
putsym('\n');
if(flags.standout)
standoutbeg();
putstr("Hit ");
putstr(flags.cbreak ? "space" : "return");
putstr(" to continue: ");
if(flags.standout)
standoutend();
xwaitforspace(s);
}
char morc; /* tell the outside world what char he used */
xwaitforspace(s)
register char *s; /* chars allowed besides space or return */
{
register int c;
morc = 0;
while((c = readchar()) != '\n') {
if(flags.cbreak) {
if(c == ' ') break;
if(s && index(s,c)) {
morc = c;
break;
}
bell();
}
}
}
static int last_multi;
char *
parse()
{
static char inline[COLNO];
register foo;
flags.move = 1;
if(!Invisible) curs_on_u(); else home();
multi = 0;
#ifdef DGK
while((foo = readchar()) >= '0' && foo <= '9') {
multi = 10*multi+foo-'0';
if (multi < 0 || multi > LARGEST_INT)
multi = LARGEST_INT;
if (multi > 9) {
remember_topl();
home();
cl_end();
printf("Count: %d", multi);
}
last_multi = multi;
}
# ifdef REDO
if (foo == DOAGAIN || in_doagain)
multi = last_multi;
else {
savech(0); /* reset input queue */
savech(foo);
}
# endif
#else /* DGK */
while((foo = readchar()) >= '0' && foo <= '9')
multi = 10*multi+foo-'0';
#endif /* DGK */
if(multi) {
multi--;
save_cm = inline;
}
inline[0] = foo;
inline[1] = 0;
if(foo == 'g' || foo == 'G'){
inline[1] = getchar();
#ifdef REDO
savech(inline[1]);
#endif
inline[2] = 0;
}
if(foo == 'm' || foo == 'M'){
inline[1] = getchar();
#ifdef REDO
savech(inline[1]);
#endif
inline[2] = 0;
}
clrlin();
return(inline);
}
char
readchar() {
register int sym;
(void) fflush(stdout);
sym = getchar();
if(flags.toplin == 1)
flags.toplin = 2;
return((char) sym);
}
#ifdef COM_COMPL
/* Read in an extended command - doing command line completion for
* when enough character have been entered to make a unique command.
* This is just a modified getlin(). -jsb
*/
get_ext_cmd(bufp)
register char *bufp;
{
register char *obufp = bufp;
register int c;
int com_index, index;
flags.toplin = 2; /* nonempty, no --More-- required */
for(;;) {
(void) fflush(stdout);
if((c = readchar()) == EOF) {
*bufp = 0;
return;
}
if(c == '\033') {
*obufp = c;
obufp[1] = 0;
return;
}
if(c == erase_char || c == '\b') {
if(bufp != obufp) {
bufp--;
putstr("\b \b"); /* putsym converts \b */
} else bell();
} else if(c == '\n') {
*bufp = 0;
return;
} else if(' ' <= c && c < '\177') {
/* avoid isprint() - some people don't have it
' ' is not always a printing char */
*bufp = c;
bufp[1] = 0;
index = 0;
com_index = -1;
while(extcmdlist[index].ef_txt != (char *) 0){
if(!strncmp(obufp, extcmdlist[index].ef_txt,
strlen(obufp)))
if(com_index == -1) /* No matches yet*/
com_index = index;
else /* More than 1 match */
com_index = -2;
index++;
}
if(com_index >= 0){
strcpy(obufp,
extcmdlist[com_index].ef_txt);
/* finish print our string */
putstr(bufp);
bufp = obufp; /* reset it */
if(strlen(obufp) < BUFSIZ-1 &&
strlen(obufp) < COLNO)
/* set bufp at the end of our
* string
*/
bufp += strlen(obufp);
} else {
putstr(bufp);
if(bufp-obufp < BUFSZ-1 && bufp-obufp < COLNO)
bufp++;
}
} else if(c == kill_char || c == '\177') { /* Robert Viduya */
/* this test last - @ might be the kill_char */
while(bufp != obufp) {
bufp--;
putstr("\b \b");
}
} else
bell();
}
}
#endif COM_COMPL
SHAR_EOF
cat << \SHAR_EOF > amigaTermcap.c
/* SCCS Id: @(#)termcap.c 2.1 87/10/19
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
#include <stdio.h>
#include <ctype.h> /* for isdigit() */
#include "hack.h" /* for ROWNO, COLNO, *HI, *HE */
#define xputc(c) WindowPutchar(c)
#define xputs(s) WindowFPuts(s)
extern char *getenv();
extern long *alloc();
static char HO[] = "\x9BH"; /* Home */
static char CL[] = "\x1Bc"; /* Clear */
static char CE[] = "\x9BK"; /* Erase end of line */
static char UP[] = "\x0B"; /* Cursor up */
static char CM[] = "\x9B%d;%dH"; /* used with function tgoto() */
static char ND[] = "\x9BC"; /* Cursor right */
static char XD[] = "\x9BB"; /* Cursor down */
static char BC[] = "\x08"; /* Cursor left */
#ifdef MSDOSCOLOR /* creps@silver.bacs.indiana.edu */
static char SO[] = "\x9B33m"; /* Standout: Color #3 (red) */
static char SE[] = "\x9B0m";
#else
static char SO[] = "\x9B7m"; /* Inverse video */
static char SE[] = "\x9B0m";
#endif
char *CD = "\x9BJ"; /* char *CD; tested in pri.c: docorner() */
/* #if defined(DGK) || defined(SORTING) */
#ifdef DGK
# define XXX
#endif
#ifdef SORTING
# define XXX
#endif
#ifdef XXX
# ifdef MSDOSCOLOR
char *HI_OBJ = "\x9B31;42m"; /* White on Black */
char *HI_MON = "\x9B33;42m"; /* Orange on black */
char *HI = "\x9B1m"; /* Bold (hilight) */
char *HE = "\x9B0m"; /* Plain */
# else
char *HI_OBJ = "";
char *HI_MON = "";
char *HI = "\x9B4m"; /* Underline */
char *HE = "\x9B0m"; /* Plain */
# endif
#endif
#undef XXX
int CO = COLNO;
int LI = ROWNO; /* used in pri.c and whatis.c */
static char tgotobuf[20];
#define tgoto(fmt, x, y) (sprintf(tgotobuf, fmt, y+1, x+1), tgotobuf)
startup()
{
(void) Initialize(); /* This opens screen, window, console, &c */
}
start_screen()
{
}
end_screen()
{
clear_screen();
}
/* Cursor movements */
extern xchar curx, cury;
#ifdef TERMCAP
curs(x, y)
register int x, y; /* not xchar: perhaps xchar is unsigned and
curx-x would be unsigned as well */
{
if (y == cury && x == curx)
return;
if(!ND && (curx != x || x <= 3)) { /* Extremely primitive */
cmov(x, y); /* bunker!wtm */
return;
}
if(abs(cury-y) <= 3 && abs(curx-x) <= 3)
nocmov(x, y);
else if((x <= 3 && abs(cury-y)<= 3) || (!CM && x<abs(curx-x))) {
(void) putchar('\r');
curx = 1;
nocmov(x, y);
} else if(!CM) {
nocmov(x, y);
} else
cmov(x, y);
}
nocmov(x, y)
{
if (cury > y) {
if(UP) {
while (cury > y) { /* Go up. */
xputs(UP);
cury--;
}
} else if(CM) {
cmov(x, y);
} else if(HO) {
home();
curs(x, y);
} /* else impossible("..."); */
} else if (cury < y) {
if(XD) {
while(cury < y) {
xputs(XD);
cury++;
}
} else if(CM) {
cmov(x, y);
} else {
while(cury < y) {
xputc('\n');
curx = 1;
cury++;
}
}
}
if (curx < x) { /* Go to the right. */
if(!ND) cmov(x, y); else /* bah */
/* should instead print what is there already */
while (curx < x) {
xputs(ND);
curx++;
}
} else if (curx > x) {
while (curx > x) { /* Go to the left. */
xputs(BC);
curx--;
}
}
}
cmov(x, y)
register x, y;
{
xputs(tgoto(CM, x-1, y-1));
cury = y;
curx = x;
}
#else /* !TERMCAP */
curs(x, y)
register x, y;
{
if (x != curx || y != cury) {
xputs(tgoto(CM, x-1, y-1));
cury = y;
curx = x;
}
}
#endif /* TERMCAP */
#ifndef xputc
xputc(c) char c; {
(void) putchar(c, stdout);
}
#endif
#ifndef xputs
xputs(s) char *s; {
WindowFPuts(s);
}
#endif
cl_end() {
#ifdef TERMCAP
if(CE)
xputs(CE);
else { /* no-CE fix - free after Harold Rynes */
/* this looks terrible, especially on a slow terminal
but is better than nothing */
register cx = curx, cy = cury;
while(curx < COLNO) {
xputc(' ');
curx++;
}
curs(cx, cy);
}
#else
xputs(CE);
#endif
}
clear_screen() {
xputs(CL);
home();
}
home()
{
#ifdef TERMCAP
if(HO)
xputs(HO);
else if(CM)
xputs(tgoto(CM, 0, 0));
else
curs(1, 1); /* using UP ... */
#else
xputs(HO);
#endif
curx = cury = 1;
}
standoutbeg()
{
#ifdef TERMCAP
if(SO)
#endif
xputs(SO);
}
standoutend()
{
#ifdef TERMCAP
if(SE)
#endif
xputs(SE);
}
backsp()
{
xputs(BC);
curx--;
}
bell()
{
#ifdef DGKMOD
if (flags.silent) return;
#endif /* DGKMOD /**/
(void) putchar('\007'); /* curx does not change */
(void) fflush(stdout);
}
delay_output() {
/* delay 50 ms - could also use a 'nap'-system call */
Delay(2L);
}
cl_eos() /* free after Robert Viduya */
{ /* must only be called with curx = 1 */
#ifdef TERMCAP
if(CD)
xputs(CD);
else {
register int cx = curx, cy = cury;
while(cury <= LI-2) {
cl_end();
xputc('\n');
curx = 1;
cury++;
}
cl_end();
curs(cx, cy);
}
#else
xputs(CD);
#endif
}
SHAR_EOF
cat << \SHAR_EOF > amigaUnix.c
/* SCCS Id: @(#)pcunix.c 1.4 87/08/08
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* unix.c - version 1.0.3 */
/* This file collects some Unix dependencies; pager.c contains some more */
/*
* The time is used for:
* - seed for rand()
* - year on tombstone and yymmdd in record file
* - phase of the moon (various monsters react to NEW_MOON or FULL_MOON)
* - night and midnight (the undead are dangerous at midnight)
* - determination of what files are "very old"
*/
#include <stdio.h> /* mainly for NULL */
#include "hack.h" /* mainly for index() which depends on BSD */
#include <time.h>
#include <stat.h>
extern time_t time();
static struct stat buf, hbuf;
setrandom()
{
(void) srand((int) time ((time_t *) 0));
}
struct tm *
getlt()
{
time_t date;
struct tm *localtime();
(void) time(&date);
return(localtime(&date));
}
getyear()
{
return(1900 + getlt()->tm_year);
}
char *
getdate()
{
static char datestr[7];
register struct tm *lt = getlt();
(void) sprintf(datestr, "%2d%2d%2d",
lt->tm_year, lt->tm_mon + 1, lt->tm_mday);
if(datestr[2] == ' ') datestr[2] = '0';
if(datestr[4] == ' ') datestr[4] = '0';
return(datestr);
}
phase_of_the_moon() /* 0-7, with 0: new, 4: full */
{ /* moon period: 29.5306 days */
/* year: 365.2422 days */
register struct tm *lt = getlt();
register int epact, diy, golden;
diy = lt->tm_yday;
golden = (lt->tm_year % 19) + 1;
epact = (11 * golden + 18) % 30;
if ((epact == 25 && golden > 11) || epact == 24)
epact++;
return( (((((diy + epact) * 6) + 11) % 177) / 22) & 7 );
}
night()
{
register int hour = getlt()->tm_hour;
return(hour < 6 || hour > 21);
}
midnight()
{
return(getlt()->tm_hour == 0);
}
gethdate(name) char *name; {
/* old version - for people short of space */
/*
/* register char *np;
/* if(stat(name, &hbuf))
/* error("Cannot get status of %s.",
/* (np = rindex(name, '/')) ? np+1 : name);
/*
/* version using PATH from: seismo!gregc@ucsf-cgl.ARPA (Greg Couch) */
/*
* The problem with #include <sys/param.h> is that this include file
* does not exist on all systems, and moreover, that it sometimes includes
* <sys/types.h> again, so that the compiler sees these typedefs twice.
*/
#define MAXPATHLEN 80
extern char PATH[]; /* In amigaDOS.c */
register char *np, *path;
char filename[MAXPATHLEN+1];
if (index(name, '/') != NULL || (path = PATH) == NULL)
path = "";
for (;;) {
if ((np = index(path, ':')) == NULL)
np = path + strlen(path); /* point to end str */
if (np - path <= 1) /* %% */
(void) strcpy(filename, name);
else {
(void) strncpy(filename, path, np - path);
filename[np - path] = '/';
(void) strcpy(filename + (np - path) + 1, name);
}
if (stat(filename, &hbuf) == 0)
return;
if (*np == '\0')
path = "";
path = np + 1;
}
error("Cannot get status of %s.", (np = rindex(name, '/')) ? np+1 : name);
}
uptodate(fd) {
#ifndef AMIGA /* Amiga has no fstat */
if(fstat(fd, &buf)) {
pline("Cannot get status of saved level? ");
return(0);
}
if(buf.st_mtime < hbuf.st_mtime) {
pline("Saved level is out of date. ");
return(0);
}
#endif
return(1);
}
regularize(s) /* normalize file name - we don't like :'s or /'s */
register char *s;
{
register char *lp;
while((lp = index(s, ':')) || (lp = index(s, '/')))
*lp = '_';
}
SHAR_EOF
cat << \SHAR_EOF > amigaWindow.c
/*
* amigaWindow.c (C) Copyright 1988 by Olaf Seibert (KosmoSoft)
*/
/*
* Here is some very Amiga specific stuff, dealing with
* screens, windows and menus.
*/
#include "config.h"
#define HACKFONT
#undef TRUE
#undef FALSE
#undef COUNT
#include <exec/types.h>
#include <exec/alerts.h>
#include <exec/io.h>
#include <exec/devices.h>
#include <devices/console.h>
#include <intuition/intuition.h>
#include <libraries/dosextens.h>
#include "amigaMenu.c"
/* First, external declarations... */
struct Library *OpenLibrary();
struct Screen *OpenScreen();
struct Window *OpenWindow();
struct TextFont *OpenDiskFont();
struct IntuiMessage *GetMsg();
struct MenuItem *ItemAddress();
struct Process *FindTask(); /* Cheating */
long DeadKeyConvert(), OpenDevice(), CloseDevice();
extern struct Library *IconBase;
/* Now our own variables */
struct Library *IntuitionBase;
struct Screen *HackScreen;
struct Window *HackWindow;
struct Window *pr_WindowPtr;
struct IOStdReq ConsoleIO;
char Initialized = FALSE;
#ifdef HACKFONT
struct Library *GfxBase;
struct Library *DiskfontBase;
#endif
struct Device *ConsoleDevice;
#define CSI '\x9b'
#define NO_CHAR -1
#define RAWHELP 0x5F /* Rawkey code of the HELP key */
/*
* It is assumed that all multiple-character outputs are
* at most CONBUFFER characters each.
*/
#define CONBUFFER BUFSZ /* 512 */
static char ConsoleBuffer[CONBUFFER];
static unsigned short Buffered;
#define KBDBUFFER 10
static unsigned char KbdBuffer[KBDBUFFER];
static unsigned char KbdBuffered;
#define BufferQueueChar(ch) (KbdBuffer[KbdBuffered++] = ch)
/*
* It seems Intuition won't OpenDiskFont our diskFont, so we get the
* closest match, which is of course topaz/8. (and if not, it is still
* an 8-pixel font, so everything still looks ok)
*/
struct TextAttr Hack80 = {
#ifdef HACKFONT
(UBYTE *) "NetHack:Hack.font",
#else
(UBYTE *) "topaz.font",
#endif
TOPAZ_EIGHTY, FS_NORMAL, FPF_DISKFONT
};
#ifdef HACKFONT
struct TextFont *HackFont;
#endif
#define BARHEIGHT 11
#define WINDOWHEIGHT 192
#define WIDTH 640
#define DEPTH 2
struct NewScreen NewHackScreen = {
0, 0, WIDTH, BARHEIGHT + WINDOWHEIGHT, DEPTH,
0, 1, /* DetailPen, BlockPen */
HIRES,
CUSTOMSCREEN,
&Hack80, /* Font */
(UBYTE *) "NetHack 2.3 - Ported by Olaf Seibert (KosmoSoft)",
NULL, /* Gadgets */
NULL, /* CustomBitmap */
};
struct NewWindow NewHackWindow = {
/* left, top, width, height, detailpen, blockpen */
0, BARHEIGHT, WIDTH, WINDOWHEIGHT, -1, -1,
RAWKEY | MENUPICK /* | MOUSEBUTTONS | GADGETDOWN */ ,
BORDERLESS | BACKDROP | ACTIVATE,
NULL, NULL, NULL,
NULL, NULL, -1,-1,-1,-1, CUSTOMSCREEN
};
static int BufferGetchar()
{
register unsigned char *from, *to;
register int c;
register short i;
if (KbdBuffered) {
c = KbdBuffer[0];
KbdBuffered--;
to = KbdBuffer;
from = to + 1;
/* Move the remaining characters */
for (i = KbdBuffered; i > 0; i--) {
*to++ = *from++;
}
return c;
}
return NO_CHAR;
}
/*
* This should remind you remotely of DeadKeyConvert,
* but we are cheating a bit.
* We want complete control over the numeric keypad, and no
* dead keys... (they are assumed to be on Alted keys)
* Also assumed is that the IntuiMessage is of type RAWKEY.
* For some reason, IECODE_UP_PREFIX events seem to be lost when they
* occur while our console window is inactive. This is particulary
* troublesome with qualifier keys... Is this because I never
* RawKeyConvert those events???
*/
int ConvertKey(message)
register struct IntuiMessage *message;
{
static struct InputEvent theEvent;
static char numpad[] = "bjnh.lyku";
static char ctrl_numpad[] = "\x02\x0A\x0E\x08.\x0C\x19\x0B\x15";
static char shift_numpad[] = "BJNH.LYKU";
unsigned char buffer[1];
register char length;
register ULONG qualifier = message->Qualifier;
char numeric_pad, shift, control, alt;
control = (qualifier & IEQUALIFIER_CONTROL) != 0;
shift = (qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT)) != 0;
/*
* Shortcut for HELP and arrow keys... I suppose this is allowed...
* the defines are in intuition/intuition.h, and the keys
* don't serve 'text' input, normally.
* Also, parsing their escape sequences is such a mess...
*/
switch (message->Code) {
case RAWHELP:
length = '?';
goto no_arrow;
case CURSORLEFT:
length = 'h'; goto arrow;
case CURSORDOWN:
length = 'j'; goto arrow;
case CURSORUP:
length = 'k'; goto arrow;
case CURSORRIGHT:
length = 'l';
arrow:
if (control)
length &= 0x1F; /* ToControl... */
else if (shift)
length &= 0x5F; /* ToUpper... */
no_arrow:
BufferQueueChar(length);
return;
}
#ifdef BETA
if (!ConsoleDevice) { /* Should never happen */
abort(AG_IOError | AO_ConsoleDev);
return;
}
#endif
numeric_pad = (qualifier & IEQUALIFIER_NUMERICPAD) != 0;
if (alt = (qualifier & (IEQUALIFIER_LALT | IEQUALIFIER_RALT)) != 0)
/* Don't want dead keys... */
qualifier &= ~(IEQUALIFIER_LALT | IEQUALIFIER_RALT);
theEvent.ie_Class = IECLASS_RAWKEY;
theEvent.ie_Code = message->Code;
theEvent.ie_Qualifier = numeric_pad ? IEQUALIFIER_NUMERICPAD :
qualifier;
theEvent.ie_EventAddress = (APTR) *(message->IAddress);
length = RawKeyConvert(&theEvent, buffer, (long) sizeof(buffer), NULL);
if (length == 1) { /* Plain ASCII character */
length = buffer[0];
if (numeric_pad && length >= '1' && length <= '9') {
length -= '1';
if (control) {
length = ctrl_numpad[length];
} else if (shift) {
length = shift_numpad[length];
} else {
length = numpad[length];
}
}
BufferQueueChar(length);
} /* else shift, ctrl, alt, amiga, F-key, shift-tab, etc */
}
/*
* Process an incoming IntuiMessage.
* It would certainly look nicer if this could be done using a
* PA_SOFTINT message port, but we cannot call RawKeyConvert()
* during a software interrupt.
* Anyway, kbhit() is called often enough, and usually gets
* ahead of input demands, when the user types ahead.
*/
static char ProcessMessage(message)
register struct IntuiMessage *message;
{
switch(message->Class) {
case MENUPICK:
{
USHORT thismenu;
struct MenuItem *item = NULL;
thismenu = message->Code;
while (thismenu != MENUNULL) {
item = ItemAddress(&HackMenu, (ULONG) thismenu);
if (KbdBuffered < KBDBUFFER)
BufferQueueChar(item->Command); /* Unused: No COMMSEQ */
thismenu = item->NextSelect;
}
}
break;
case RAWKEY:
if (!(message->Code & IECODE_UP_PREFIX))
ConvertKey(message); /* May queue multiple characters */
break; /* but doesn't do that yet */
#if 0
case CLOSEWINDOW:
BufferQueueChar('Q');
break;
#endif
#if 0
case GADGETDOWN:
BufferQueueChar( ((struct Gadget *)message->IAddress)->GadgetID );
break;
#endif
}
ReplyMsg(message);
}
/*
* Get all incoming messages and fill up the keyboard buffer,
* thus allowing Intuition to (maybe) free up the IntuiMessages.
* Return when no more messages left, or keyboard buffer half full.
* We need to do this since there is no one-to-one correspondence
* between characters and incoming messages.
*/
int kbhit()
{
register struct IntuiMessage *message;
while( (KbdBuffered < KBDBUFFER / 2) &&
(message = GetMsg(HackWindow->UserPort)) )
ProcessMessage(message);
return KbdBuffered;
}
/*
* Get a character from the keyboard buffer, waiting if
* not available.
*/
int WindowGetchar()
{
while ( !kbhit() ) {
Wait( 1L << HackWindow->UserPort->mp_SigBit );
}
return BufferGetchar();
}
/*
* Flush the output waiting in the console output buffer.
*/
void WindowFlush()
{
#ifdef BETA
if (!ConsoleDevice) { /* Should never happen */
abort(AG_IOError | AO_ConsoleDev);
return;
}
#endif
if (Buffered) {
ConsoleIO.io_Command = CMD_WRITE;
ConsoleIO.io_Data = (APTR)ConsoleBuffer;
ConsoleIO.io_Length = Buffered;
DoIO(&ConsoleIO);
Buffered = 0;
}
}
/*
* Queue a single character for output to the console screen.
*/
int WindowPutchar(c)
char c;
{
if (Buffered >= CONBUFFER)
WindowFlush();
ConsoleBuffer[Buffered++] = c;
}
/*
* Queue an entire string for output to the console screen,
* flushing the existing characters first, if necessary.
* Do not append a newline.
*/
void WindowFPuts(string)
char *string;
{
register int len = _BUILTIN_strlen(string);
if (len + Buffered >= CONBUFFER)
WindowFlush();
_BUILTIN_strcpy(ConsoleBuffer + Buffered, string);
Buffered += len;
}
/*
* Queue an entire string for output to the console screen,
* flushing the existing characters first, if necessary.
* Append a newline.
*/
void WindowPuts(string)
char *string;
{
WindowFPuts(string);
WindowPutchar('\n');
}
/*
* Queue a formatted string for output to the console screen,
* flushing the existing characters first, if necessary.
*/
void WindowPrintf(fmt, args, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
char *fmt;
long args, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9;
{
#ifdef AZTEC_C /* Efficient but not portable */
format(WindowPutchar, fmt, &args);
#else
WindowFlush(); /* Don't know if all will fit */
# ifdef __STDC__ /* Cheap and portable way */
vsprintf(ConsoleBuffer, fmt, &args);
# else /* Expensive... */
sprintf(ConsoleBuffer, fmt, args, arg2, arg3, arg4, arg5, arg6, arg7, arg8,
arg9);
# endif
ConsoleIO.io_Command = CMD_WRITE;
ConsoleIO.io_Data = (APTR)ConsoleBuffer;
ConsoleIO.io_Length = -1;
DoIO(&ConsoleIO);
#endif
}
void CleanUp()
{
struct IntuiMessage *msg;
/* Clean up resources */
if (ConsoleIO.io_Device) {
CloseDevice(&ConsoleIO);
ConsoleDevice = NULL;
}
if (HackWindow) {
FindTask(NULL)->pr_WindowPtr = (APTR) pr_WindowPtr;
ClearMenuStrip(HackWindow);
Forbid();
while (msg = GetMsg(HackWindow->UserPort))
ReplyMsg(msg);
CloseWindow(HackWindow);
Permit();
HackWindow = NULL;
}
if (HackScreen) {
CloseScreen(HackScreen);
HackScreen = NULL;
}
/* if (IconBase) {
CloseLibrary(IconBase);
IconBase = NULL;
} */
#ifdef HACKFONT
if (HackFont) {
CloseFont(HackFont);
HackFont = NULL;
}
if (DiskfontBase) {
CloseLibrary(DiskfontBase);
DiskfontBase = NULL;
}
if (GfxBase) {
CloseLibrary(GfxBase);
GfxBase = NULL;
}
#endif
if (IntuitionBase) {
CloseLibrary(IntuitionBase);
IntuitionBase = NULL;
}
Initialized = FALSE;
}
void abort(rc)
long rc;
{
#ifdef CHDIR
extern char orgdir[];
chdir(orgdir);
#endif
if (Initialized && ConsoleDevice) {
printf("\n\nAbort with alert code %08lx...\n", rc);
getret();
} else
Alert(rc, 0L);
CleanUp();
#undef exit
exit(rc);
}
/* Used by library routines, and the debugger */
void _abort()
{
abort(-10L);
}
/*
* Open everything we need.
*/
void Initialize()
{
if (Initialized)
return;
if ( (IntuitionBase = OpenLibrary("intuition.library", LIBRARY_VERSION))
== NULL)
abort(AG_OpenLib | AO_Intuition);
#ifdef HACKFONT
if ( (GfxBase = OpenLibrary("graphics.library",LIBRARY_VERSION)) == NULL)
abort(AG_OpenLib | AO_GraphicsLib);
/*
* Force our own font to be loaded, if possible.
* If we can open diskfont.library, but not our font, we can close
* the diskfont.library again since it just wastes memory.
* Even if we can open the font, we don't need the diskfont.library
* anymore, since CloseFont is a graphics.library function.
*/
if (DiskfontBase = OpenLibrary("diskfont.library", LIBRARY_VERSION)) {
HackFont = OpenDiskFont(&Hack80);
CloseLibrary(DiskfontBase);
DiskfontBase = NULL;
}
#endif
/* if ( (IconBase = OpenLibrary("icon.library",LIBRARY_VERSION)) == NULL)
abort(AG_OpenLib | AO_IconLib); */
/*
* Now Intuition is supposed to use our HackFont for the screen,
* since we have a corresponding TextAttr, but it *doesn't*.
* So, we need to do a SetFont() a bit later on.
*/
if ( (HackScreen = OpenScreen(&NewHackScreen)) == NULL)
abort(AN_OpenScreen & ~AT_DeadEnd);
NewHackWindow.Screen = HackScreen;
if ( (HackWindow = OpenWindow(&NewHackWindow)) == NULL)
abort(AN_OpenWindow & ~AT_DeadEnd);
SetMenuStrip(HackWindow,&HackMenu);
{
register struct Process *myProcess = FindTask(NULL);
pr_WindowPtr = (struct Window *)myProcess->pr_WindowPtr;
myProcess->pr_WindowPtr = (APTR) HackWindow;
}
#ifdef HACKFONT
if (HackFont)
SetFont(HackWindow->RPort, HackFont);
#endif
ConsoleIO.io_Data = (APTR) HackWindow;
ConsoleIO.io_Length = sizeof(*HackWindow);
if (OpenDevice("console.device",0L , &ConsoleIO, 0L) != 0)
abort(AG_OpenDev | AO_ConsoleDev);
ConsoleDevice = ConsoleIO.io_Device;
Buffered = 0;
KbdBuffered = 0;
/* set CRMOD on */
WindowFPuts("\x9B20h");
Initialized = TRUE;
}
SHAR_EOF
# End of shell archive
exit 0
--
Bob Page, U of Lowell CS Dept. page@swan.ulowell.edu ulowell!page
Have five nice days.